import {url} from "inspector";

const fs: any = require('fs')
const request = require('request');

interface loginParams {
    email: string;
    password: string
}

interface IReqParams {
    name: string
}

class YAPI {
    // 登录域名
    host: string;
    // 项目ID
    pid: number;
    // 根据host和pid生成的yapi地址
    yapiAddress: string;
    // 错误信息
    error: string;
    // 登录请求后获取的cookie
    cookie: string;

    /**
     * 构造函数
     * @param host yapi的地址 主要用于生成mock地址和快速链接到浏览器
     * @param pid 项目ID
     * @param options
     */
    constructor(host: string, pid: number) {
        this.host = host
        this.pid = pid
        this.yapiAddress = `${host}/project/${pid}`;
    }

    /**
     * 登录参数 {email: '', password: ''}
     * @param params
     */
    login(params: loginParams) {
        const config: any = {
            url: this.host + '/api/user/login',
            method: 'POST',
            headers: {},
            form: params,
        };
        return new Promise((resolve) => {
            request(config, (e, r) => {
                this.cookie = r.headers['set-cookie']
                resolve(r)
            });
        })
    }

    parseContent(content: any) {
        const startTime: number = new Date().getTime()
        for (let i of content) {
            i.name = i.name.replace(/\//g, '_')
            const list: Array<any> = i.list
            const fileContent: string = this._getTemplateFile().replace(
                '{REQUEST_FUNCTIONS}',
                list.map(_item => {
                    let {path, method, req_params} = _item
                    path = path.replace(/\/\//g, '/')
                    if (path == '') return ''
                    return this.getFunctionTemplate()
                        .replace('{__COMMENT__}', this._getComments(_item))
                        .replace('{__FUNCTION_NAME}', this._getFunctionName(path, method))
                        .replace('{__PATH_PARAMS__}', this._getPathParams(req_params))
                        .replace('{__URL__}', this._getPath(path))
                        .replace('{__METHOD__}', method)
                        .replace('{PARAMS_OBJECT_PROPERTY}', this._getParamsObjectProperty(method))
                        .replace('{HTTP_FUNCTION}', 'axios')
                }).join('')
            )
            // 写文件
            this._writeFile(__dirname + '/api/' + i.name + '.js', fileContent)
        }
        const endTime: number = new Date().getTime()
        console.log('转化使用时间', endTime - startTime, 'ms')
    }

    _getTemplateFile() {
        return `import axios from 'axios'
        
{REQUEST_FUNCTIONS}
`
    }

    startTask(convertFunction?: Function) {
        if (!this.cookie) {
            this._setError('你还没有登录')
        } else {
            const opts = {
                url: `${this.host}/api/plugin/export?type=json&pid=${this.pid}&status=all`,
                headers: {
                    Cookie: this.cookie,
                }
            };
            request(opts, (e, r) => {
                try {
                    // 如果有自定义方法则让自定义方法去处理他 YAPI2JS不做任何干预 甚至不屑文件
                    if (convertFunction) {
                        convertFunction(JSON.parse(r.body))
                    } else {
                        this.parseContent(JSON.parse(r.body))
                    }
                } catch (e) {
                    console.error(e)
                }
            });
        }
    }

    getFunctionTemplate() {
        return `
{__COMMENT__}
export function {__FUNCTION_NAME}({__PATH_PARAMS__}data, options = {}) {
  return {HTTP_FUNCTION}({
    url: \`{__URL__}\`,
    method: '{__METHOD__}',
    {PARAMS_OBJECT_PROPERTY}: data,
    ...options
  })
}

`
    }

    _getPath(path: string) {
        return path.replace(/{/g, '${')
    }

    _getParamsObjectProperty(method: string) {
        return method.toLowerCase() == 'get' ? 'params' : 'data'
    }

    _getPathParams(pathParams: Array<IReqParams>) {
        // 替换路径的中的参数
        return pathParams.length ? pathParams.map(v => v.name).join(', ') + ', ' : ''
    }

    /**
     * 生成方法名字
     * @private
     * @param path
     * @param method
     */
    _getFunctionName(path: string, method: string) {
        return method.toLowerCase() + this._filter(path, 'url')
            .replace(/\_|-/g, '/')
            .split('/').filter(item => !!item)
            .map(item => this._letterToUpper(item, 0))
            .join('')
    }

    /**
     * 生成注释
     * @param item
     * @private
     */
    _getComments(item: any) {
        let str: string = `
/**
 * ${item.title}
 * YAPI: ${this.yapiAddress}/interface/api/${item._id}
 * 备注: ${this._filterHtmlTag((item.desc || '').trim()).replace(/\n/g, `\n$  * `)}`

        const obj: any = {
            req_params: '请求参数 - 路径中的标量',
            req_body_other: '请求参数 - body - json',
            req_body_form: '请求参数 - body - formData',
        }

        for (let i in obj) {
            let commentItem = item[i]
            if (commentItem && commentItem.length) {
                if (i === 'req_params') {
                    commentItem = commentItem.map(item => ({name: item.name, desc: item.desc}))
                }
                if (typeof commentItem === 'string') {
                    str += `\n * ${obj[i]}\n` + commentItem
                } else {
                    str += `\n * ${obj[i]}\n` + JSON.stringify(commentItem, null, 2)
                }
            }
        }

        return str + '\n */'
    }

    _filterHtmlTag(value: string) {
        if (!value) return ''
        return value.trim().replace(/<[^<>]+>/g, '')
            .replace('<br>', '')
            .replace('&nbsp;', '')
            .replace(/\n\n/g, '')
    }


    /**
     * 字母转大写
     * @param value
     * @private
     */
    _letterToUpper(value: string, number: number) {
        if (number > value.length - 1 || value === '') {
            this._setError('索引大于字符串长度了');
            return value
        }
        return value.replace(value[0], value[0].toUpperCase())
    }

    _writeFile(filePath: string, value: string) {
        fs.writeFileSync(filePath, value)
    }

    /**
     * 过滤方法 过滤掉一些奇奇怪怪的东西
     * @param value
     * @private
     */
    _filter(value: string, type: string) {
        if (type === 'url') {
            return value.replace(/\{|\}|\./g, '')
        }
        return value
    }

    _setError(value: string) {
        this.error = value
        throw new Error(value)
    }

    getError() {
        return this.error
    }
}

module.exports = YAPI
